package rpc_server

import (
	"io"
	"net"
	"tcp_server/src/common_util"
	"tcp_server/src/utils"
)

type RPCServer struct {
	functionsMap map[string]func(args ...interface{}) (interface{}, error)
	services     map[string]interface{}
}

func NewRPCServer() *RPCServer {
	return &RPCServer{
		functionsMap: make(map[string]func(args ...interface{}) (interface{}, error)),
		services:     make(map[string]interface{}),
	}
}

// RegisterMethod 注册方法
func (r *RPCServer) RegisterMethod(methodName string, method func(args ...interface{}) (interface{}, error)) {
	r.functionsMap[methodName] = method
}

func (r *RPCServer) RegisterService(serviceName string, service interface{}) {
	r.services[serviceName] = service
}

func (r *RPCServer) StartServer(address string) error {
	listener, err := net.Listen("tcp", address)
	if err != nil {
		common_util.ErrorLogger.Printf("RPC 服务启动出现错误 ：%v", err)
	}
	defer closeResource(listener)

	common_util.InfoLogger.Printf("RPC 服务启动成功，监听地址: %s", address)

	for {
		conn, err := listener.Accept()
		if err != nil {
			common_util.ErrorLogger.Printf("接受连接出现错误: %v", err)
			continue
		}
		// 处理客户端请求
		go r.handleConnection(conn)
	}
}

func (r *RPCServer) handleConnection(conn net.Conn) {
	defer closeResource(conn)
	for {
		// 解码 RPC 请求
		req, err := r.readRequest(conn)
		if err != nil {
			if err == io.EOF {
				common_util.ErrorLogger.Printf("客户端断开连接")
			} else {
				common_util.ErrorLogger.Printf("连接出现异常: %v", err)
			}
			return
		}
		// 调用方法
		var res common_util.RPCResponse
		fn, ok := r.functionsMap[req.Method]
		if !ok {
			res.Error = &common_util.RPCError{Message: "服务端不存在该方法"}
		} else {
			res.Result, err = fn(req.Params...)
			if err != nil {
				res.Error = &common_util.RPCError{Message: err.Error()}
			}
		}
		// 回填序列号
		res.SeqNo = req.SeqNo
		// 发送响应
		if err := r.sendResponse(conn, res); err != nil {
			common_util.ErrorLogger.Printf("发送响应出现失败: %v", err)
			return
		}
	}
}

// 读取 RPC 请求
func (r *RPCServer) readRequest(conn net.Conn) (*common_util.RPCRequest, error) {
	var req common_util.RPCRequest
	decoder := utils.NewJSONDecoder(conn)
	if err := decoder.Decode(&req); err != nil {
		return nil, err
	}
	return &req, nil
}

// 发送 RPC 响应
func (r *RPCServer) sendResponse(conn net.Conn, res common_util.RPCResponse) error {
	encoder := utils.NewJSONEncoder(conn)
	return encoder.Encode(res)
}

// 关闭资源
func closeResource(resource io.Closer) {
	if resource == nil {
		return
	}
	err := resource.Close()
	if err != nil {
		common_util.ErrorLogger.Printf("关闭连接资源出现错误: %v", err)
	}
}
